/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xui_lib.component.edittext;

import ohos.agp.components.AttrHelper;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.Text;
import ohos.agp.components.TextField;
import ohos.agp.components.element.VectorElement;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.utils.Point;
import ohos.app.Context;
import ohos.multimodalinput.event.TouchEvent;

import com.xuexiang.xui_lib.ResourceTable;
import com.xuexiang.xui_lib.util.AttrValue;
import com.xuexiang.xui_lib.util.ElementHelper;

import java.util.ArrayList;

/**
 * 自定义的可清除全部的输入框
 *
 * @since 2021-04-07
 */
public class ClearEditText extends TextField
    implements Component.FocusChangedListener, Text.TextObserver, Component.TouchEventListener {
    private static final int FOUR = 4;
    private static final int TWO = 2;
    private static final int SIX = 6;
    private static final int TWENTY = 20;
    private static final int TWENTYONE = 21;
    private int mExtraClickArea; // 增大点击区域
    private VectorElement mClearDrawable; // 删除按钮的引用
    private ArrayList<OnTextCursorChangedListener> textCursorChangedListeners = new ArrayList<>();
    private ArrayList<OnFocusChangedListener> focusChangedListeners = new ArrayList<>();
    private boolean isDrawable = false;
    //private boolean isFocusFlag = true;
    private Paint paint = new Paint();

    {
        paint.setStyle(Paint.Style.STROKE_STYLE);
        paint.setStrokeWidth(FOUR);
    }

    private Point start;
    private Point end;
    private boolean isInputError = false;

    /**
     * 构造函数
     *
     * @param context
     */
    public ClearEditText(Context context) {
        this(context, null);
    }

    /**
     * 构造函数
     *
     * @param context
     * @param attrSet
     */
    public ClearEditText(Context context, AttrSet attrSet) {
        this(context, attrSet, null);
    }

    /**
     * 构造函数
     *
     * @param context
     * @param attrSet
     * @param styleName
     */
    public ClearEditText(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        init(attrSet);
    }

    /**
     * 初始化
     *
     * @param attrSetInit
     */
    private void init(AttrSet attrSetInit) {
        isDrawable = AttrValue.get(attrSetInit, "drawable", false); // 是否使用默认图片
        initSize();
        initLine();
        setCursorChangedListener(new CursorChangedListener() {
            @Override
            public void onCursorChange(TextField textField, int i, int i1) {
                if (textCursorChangedListeners.size() > 0) {
                    for (OnTextCursorChangedListener listener : textCursorChangedListeners) {
                        listener.onCursorChange(textField, i, i1);
                    }
                }
            }
        });
        setFocusChangedListener(new FocusChangedListener() {
            @Override
            public void onFocusChange(Component component, boolean isFocused) {
                if (focusChangedListeners.size() > 0) {
                    for (OnFocusChangedListener listener : focusChangedListeners) {
                        listener.onFocusChange(component, isFocused);
                    }
                }
                invalidate();
            }
        });
    }

    /**
     * 确认输入框大小
     */
    private void initSize() {
        setEstimateSizeListener(new EstimateSizeListener() {
            @Override
            public boolean onEstimateSize(int i, int i1) {
                int width = EstimateSpec.getSize(i);
                int height = EstimateSpec.getSize(i1);
                start = new Point(0, height - paint.getStrokeWidth());
                end = new Point(width, height - paint.getStrokeWidth());
                return false;
            }
        });
    }

    /**
     * 绘制输入框底部的线条
     */
    private void initLine() {
        addDrawTask(new DrawTask() {
            @Override
            public void onDraw(Component component, Canvas canvas) {
                if (isFocused()) {
                    paint.setStrokeWidth(SIX);
                    if (isInputError) {
                        paint.setColor(ElementHelper.getColor(getContext(), ResourceTable.Color_red_light));
                    } else {
                        paint.setColor(ElementHelper.getColor(getContext(), ResourceTable.Color_blue_light));
                    }
                    paint.setMaxLines(1);
                    canvas.drawLine(start, end, paint);
                    initAttrs(getContext());
                } else {
                    if (isInputError) {
                        paint.setStrokeWidth(SIX);
                        paint.setColor(ElementHelper.getColor(getContext(), ResourceTable.Color_red_light));
                    } else {
                        paint.setStrokeWidth(FOUR);
                        paint.setColor(ElementHelper.getColor(getContext(), ResourceTable.Color_gray_light));
                    }
                    paint.setMaxLines(1);
                    canvas.drawLine(start, end, paint);
                    initAttrs(getContext());
                }
            }
        });
    }

    /**
     * setInputError
     *
     * @param isInputError1
     */
    public void setInputError(boolean isInputError1) {
        this.isInputError = isInputError1;
        invalidate();
    }

    /**
     * isInputError
     *
     * @return boolean
     */
    public boolean isInputError() {
        return this.isInputError;
    }

    /**
     * addTextCursorChangedListener
     *
     * @param listener
     */
    public void addTextCursorChangedListener(OnTextCursorChangedListener listener) {
        if (!textCursorChangedListeners.contains(listener)) {
            this.textCursorChangedListeners.add(listener);
        }
    }

    /**
     * removeTextCursorChangedListener
     *
     * @param listener
     */
    public void removeTextCursorChangedListener(OnTextCursorChangedListener listener) {
        this.textCursorChangedListeners.remove(listener);
    }

    /**
     * addOnFocusChangedListener
     *
     * @param listener
     */
    public void addOnFocusChangedListener(OnFocusChangedListener listener) {
        if (!focusChangedListeners.contains(listener)) {
            this.focusChangedListeners.add(listener);
        }
    }

    /**
     * removeOnFocusChangedListener
     *
     * @param listener
     */
    public void removeOnFocusChangedListener(OnFocusChangedListener listener) {
        this.focusChangedListeners.remove(listener);
    }

    /**
     * 输入文字
     *
     * @param text
     */
    @Override
    public void setText(String text) {
        super.setText(text);
    }

    /**
     * 当ClearEditText焦点发生变化的时候，判断里面字符串长度设置清除图标的显示与隐藏
     *
     * @param component component
     * @param isBitmapFlag isBitmapFlag
     */
    @Override
    public void onFocusChange(Component component, boolean isBitmapFlag) {
        if (isBitmapFlag) {
            int length = getText() != null ? getText().length() : 0;
            setClearIconVisible(length > 0);
        } else {
            setClearIconVisible(false);
        }
    }

    /**
     * 文本变化监听
     *
     * @param s
     * @param i
     * @param i1
     * @param i2
     */
    @Override
    public void onTextUpdated(String s, int i, int i1, int i2) {
        setClearIconVisible(s.length() > 0); // s:指示当前文本 i:指示要添加的文本的开始位置 i1:指示旧文本的长度。 i2:指示要添加的文本的长度。
    }

    /**
     * 输入框内删除按钮的设置
     *
     * @param context
     */
    private void initAttrs(Context context) {
        mExtraClickArea = AttrHelper.vp2px(TWENTY, context);
        if (isDrawable) {
            mClearDrawable = new VectorElement(context, ResourceTable.Graphic_xui_ic_default_clear_btn_blue);
        }
        if (mClearDrawable == null) {
            mClearDrawable = new VectorElement(context,
                ResourceTable.Graphic_xui_ic_default_clear_btn); // 获取EditText的DrawableRight,假如没有设置我们就使用默认的图片
        }
        mClearDrawable.setBounds(0, 0,
            AttrHelper.vp2px(TWENTYONE, getContext()), AttrHelper.vp2px(TWENTYONE, getContext()));
        setClearIconVisible(false); // 设置为隐藏图标
        addTextObserver(this); // 设置输入框里面内容发生改变的监听
        setTouchEventListener(this); // 设置清楚按钮的监听
    }

    /**
     * 设置清除图标的显示与隐藏，调用setAroundElementsPadding为EditText绘制上去
     *
     * @param isVisible
     */
    protected void setClearIconVisible(boolean isVisible) {
        VectorElement endBitmap = isVisible ? mClearDrawable : null;
        setAroundElementsRelative(null, null, endBitmap, null);
    }

    @Override
    public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
        if (getAroundElementsRelative()[TWO] != null) {
            if (touchEvent.getAction() == TouchEvent.PRIMARY_POINT_UP) {
                boolean touchable = isTouchable(touchEvent);
                if (touchable) {
                    this.setText("");
                    setClearIconVisible(false);
                }
            }
        }
        return true;
    }

    private boolean isTouchable(TouchEvent event) {
        if (isRtl()) {
            return event.getPointerScreenPosition(0).getX() > getPaddingLeft() - mExtraClickArea
                && event.getRadius(0) < getPaddingLeft() + mClearDrawable.getWidth() + mExtraClickArea;
        } else {
            return event.getPointerScreenPosition(0).getX()
                > getWidth() - getPaddingRight() - mClearDrawable.getWidth() - mExtraClickArea
                && event.getRadius(0) < getWidth() - getPaddingRight() + mExtraClickArea;
        }
    }

    /**
     * OnTextCursorChangedListener
     *
     * @since 2021-04-07
     */
    public interface OnTextCursorChangedListener {
        /**
         * onCursorChange
         *
         * @param textField
         * @param posStart
         * @param posAfter
         */
        void onCursorChange(TextField textField, int posStart, int posAfter);
    }

    /**
     * OnFocusChangedListener
     *
     * @since 2021-04-07
     */
    public interface OnFocusChangedListener {
        /**
         * onFocusChange
         *
         * @param component
         * @param isFocused
         */
        void onFocusChange(Component component, boolean isFocused);
    }
}
